import ij.ImagePlus;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;


import java.awt.Color;


import java.awt.Font;

import java.awt.Polygon;
import java.io.PrintStream;

import java.util.Locale;
import java.util.Random; 



import pluginUtils.Circle;
import pluginUtils.CircleArrangement;
import pluginUtils.Complexe; 
import pluginUtils.DoyleCircle;
import pluginUtils.Droite;
import pluginUtils.MobiusTransform;
import pluginUtils.CircleInversion;
import pluginUtils.PackCircle;
import pluginUtils.Point2D;
import pluginUtils.Pos3D;
import pluginUtils.Sphere;
import pluginUtils.SphereInversion;


public class GenericDrawerIntersection extends ImagePlus implements PlugIn{
	{Locale.setDefault(Locale.US); }
	
	private ImageProcessor primeIP; 
	private int X=2000,Y=2000; // image size
	
	private PrintStream output;
	private double xShift=0; 
	private double zShift=0; 
	private double limit,lmoins; 
	
	

	private Random generator=new Random(); // One always needs some randomness
	
	// For the scaling of the image
	private double x0=0,x1=1,y0=0,y1=1;
	private double acoef,ccoef,vcoef,wcoef; 
	
	private String[] palette={"Yellow","Red","Blue","Green","White","NavyBlue","Turquoise","Orange"};
	private Color[] palette1={Color.YELLOW,Color.RED,Color.BLUE,Color.GREEN,Color.MAGENTA,Color.ORANGE};
	public void setCoefs(){
		acoef=X/(x1-x0); 
		vcoef=Y/(y1-y0); 
		ccoef=-acoef*x0; 
		wcoef=-vcoef*y0; 
	}
	 
	
	
	public void setBounds(double xl,double xu,double yl,double yu){
		x0=xl; 
		x1=xu;
		y0=yl;
		y1=yu; 
	}
	
	private void drawCircle(PackCircle c){
		//if(intersect(c))return; 
		
		//if(c.getRadius()<0.1) return; 
		int intX=(int)(c.getX()*acoef+ccoef);
		int intY=(int)(c.getY()*vcoef+wcoef);
		int intRx=(int)(c.getRadius()*acoef);
		int intRy=(int)(c.getRadius()*vcoef);
		int rank=((int)(c.getCouleur()*60))%6; 
	
			
			double Xs=c.getX(); 
			double Ys=c.getY(); 
			double rapp=Xs*Xs+Ys*Ys+1; 
			double u=Xs/rapp; 
			double v=Ys/rapp; 
			double w=(Xs*Xs+Ys*Ys)/rapp;
			
			double Xsr=c.getX(); 
			double Ysr=c.getY()+c.getRadius(); 
			double rappr=Xsr*Xsr+Ysr*Ysr+1; 
			double ur=Xsr/rappr; 
			double vr=Ysr/rappr; 
			double wr=(Xsr*Xsr+Ysr*Ysr)/rappr;
		
			double nrad=(u-ur)*(u-ur)+(v-vr)*(v-vr)+(w-wr)*(w-wr);
			//nrad=Math.sqrt(nrad)*1.414; 
			
			String s="sphere{<"+u+","+v+","+w+">,";
			
			
			s+=nrad; 
			s+=" texture{Texture"+rank+"} finish{Finish"+rank+"}}"; 
			output.println(s);
		
	}
	private void drawCircle(Point2D C,double r){
		double xCenter=C.getX(); 
		double yCenter=C.getY(); 
	 
		
		int intX=(int)((xCenter)*acoef+ccoef);
		int intY=Y-(int)((yCenter)*vcoef+wcoef);
		int intRx=(int)(r*acoef);
		int intRy=(int)(r*vcoef);
		
		
		primeIP.drawOval(intX-intRx,intY-intRy,intRx*2,intRy*2);
	}
	
	private void drawColoredCircle(PackCircle c){
		double xCenter=c.getX(); 
		double yCenter=c.getY(); 
		//if(c.getRadius()<0.001) return ; 
		
		int intX=(int)((xCenter-xShift)*acoef+ccoef);
		int intY=(int)((yCenter-zShift)*vcoef+wcoef);
		int intRx=(int)(c.getRadius()*acoef);
		int intRy=(int)(c.getRadius()*vcoef);
		
		
		primeIP.drawOval(intX-intRx,intY-intRy,intRx*2,intRy*2);
		
		/*
		primeIP.moveTo(intX,intY); 
		primeIP.drawString(c.getMyOrder()+"");
		*/
		
		String s="sphere{<"+xCenter+",0,"+yCenter+">,";
		s+=c.getRadius(); 
		s+=" scale 0.4*y texture{Texture"+generator.nextInt(7)+"} finish{Finish0}}"; 
		System.out.println(s); 
		output.println(s);
	
	}
	private void drawPoint(double x,double y){
		int intX=(int)(x*acoef+ccoef);
		int intY=Y-(int)(y*vcoef+wcoef);
		primeIP.fillOval(intX-10,intY-10,20,20);
	}
	
	private void drawPoint(Point2D A){
		drawPoint(A.getX(),A.getY()); 
	}
	
	private void drawTriangle(double[] X,double[] Y){
		int xint[]=new int[3]; 
		int yint[]=new int[3];
		for(int i=0;i<3;i++){
			xint[i]=(int)(X[i]*acoef+ccoef); 
			yint[i]=(int)(Y[i]*vcoef+wcoef);
		}
		primeIP.fillPolygon(new Polygon(xint,yint,3)); 
		
	}
	
	private void drawTriangleEqui(double[] X,double[] Y){
		double XP[]=new double[3]; 
		double YP[]=new double[3];
		for(int i=0;i<3;i++){

			XP[i]=(X[i]+Y[i]/2);
			YP[i]=(Math.sqrt(3)/2*Y[i]);

	/*
			XP[i]=(X[i]+Y[i]/2); ///Math.sqrt(2);
			YP[i]=(Math.sqrt(3)/2*Y[i]); ///Math.sqrt(2);
			*/

		}
		drawTriangle(XP,YP); 
		
	}
	
	
	
	private void drawLine(double xd,double yd,double xf,double yf){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		primeIP.drawLine(XD,Y-YD,XF,Y-YF); 
	}
	
	private void drawLine(Point2D A,Point2D B){
		drawLine(A.getX(),A.getY(),B.getX(),B.getY()); 
	}
		

	
	public void drawDroite(Droite d){
		double y1=d.getY(limit);
		double y2=d.getY(lmoins); 
		double x1=d.getX(limit); 
		double x2=d.getX(lmoins);
		Point2D p1[]=new Point2D[2]; 
		int indice=0; 
		if((y1>=lmoins)&&(y1<=limit))
			p1[indice++]=new Point2D(limit,y1); 
		if((y2>=lmoins)&&(y2<=limit))
			p1[indice++]=new Point2D(lmoins,y2); 
		if((x1>=lmoins)&&(x1<=limit))
			p1[indice++]=new Point2D(x1,limit); 
		if((x2>=lmoins)&&(x2<=limit))
			p1[indice++]=new Point2D(x2,lmoins);
		
		drawLine(p1[0],p1[1]); 
		
	}
	
	
	
	public void run(String arg) {
		primeIP = new ColorProcessor(X,Y);
		double r2=Math.sqrt(2);
		
		 limit=1.5; 
		 lmoins=-limit;
	
		setBounds(lmoins,limit,lmoins,limit); 
		setCoefs(); 
		
		
		
		
		
		
		Polygon background=new Polygon(new int[]{0,0,X,Y},new int[]{0,X,Y,0},4);
		primeIP.setColor(Color.WHITE);
		
		primeIP.fillPolygon(background);
		
		
		primeIP.setFont(new Font(null,Font.ITALIC,60));
		primeIP.setColor(Color.BLACK);
		primeIP.setLineWidth(3); 
		
		drawLine(lmoins,0,limit,0); 
		drawLine(0,lmoins,0,limit); 

		setProcessor("Verifying", primeIP);
		
		/*
		Droite J0R0=new Droite(J0,R0); 
		Droite B1J1=new Droite(B1, J1);
		Point2D I0=Droite.intersection(J0R0, B1J1); 
		drawPoint(I0);
		System.out.println(Point2D.distance(R0,I0)/Point2D.distance(R0, J0)); 
		
		Droite G0R0=new Droite(G0,R0); 
		Droite B1G1=new Droite(B1, G1);
		Point2D I1=Droite.intersection(G0R0, B1G1);
		drawPoint(I1);
		System.out.println(Point2D.distance(R0,I1)/Point2D.distance(R0, G0)); 
		*/
		
		
		Point2D B0=new Point2D( 0.121218,  -0.686903);  
		Point2D Y0=new Point2D ( -0.686903,  0.121218);  
		Point2D R0=new Point2D ( -0.121218,  0.686903); 
		Point2D G0=new Point2D( 0.686903,  -0.121218); 
		Droite B0Y0=new Droite(B0,Y0); 
		Droite B0G0=new Droite(B0,G0);
		Droite R0G0=new Droite(R0,G0); 
		Droite R0Y0=new Droite(R0,Y0);
		drawLine(B0,Y0); 
		drawLine(B0,G0);
		drawLine(R0,G0); 
		drawLine(R0,Y0);
		
		
		primeIP.setColor(Color.GREEN); 
		
		Pos3D BT6=new Pos3D ( -0.192270, 1.173747, 0.179668);
		Pos3D YT6=new Pos3D( 0.057453, 0.519963, 1.083175) ;
		Pos3D GT6=new Pos3D ( 0.797944, 0.411927, 0.800332) ;
		Pos3D RT6=new Pos3D	 ( 0.548221, 1.065710, -0.103175) ;

		
		
		double prop=(0.98-YT6.getY())/(BT6.getY()-YT6.getY()); 
		System.out.println("---> "+prop);
		//prop=1-prop; 
		Point2D I1=new Point2D(prop*BT6.getX()+(1-prop)*YT6.getX(),prop*BT6.getZ()+(1-prop)*YT6.getZ());
		drawPoint(I1);
		
		
		double prop2=(0.98-RT6.getY())/(GT6.getY()-RT6.getY()); 
		System.out.println("---> "+prop2);
		//prop=1-prop; 
		Point2D I2=new Point2D(prop2*GT6.getX()+(1-prop2)*RT6.getX(),prop2*GT6.getZ()+(1-prop2)*RT6.getZ());
		drawPoint(I2);
		drawLine(I1,I2); 
		
		Point2D inter=Droite.intersection(new Droite(I1,I2),new Droite(G0,R0));
		drawPoint(inter);
		
		Point2D B6=new Point2D( -0.192270, 0.179668);  
		Point2D Y6=new Point2D( 0.057453,1.083175); 
		Point2D R6=new Point2D( 0.797944, 0.800332); 
		Point2D G6=new Point2D( 0.548221,-0.103175);  
		Droite B6Y6=new Droite(B6,Y6); 
		Droite B6G6=new Droite(B6,G6);
		Droite R6G6=new Droite(R6,G6); 
		Droite R6Y6=new Droite(R6,Y6);
		drawLine(B6,Y6); 
		drawLine(B6,G6);
		drawLine(R6,G6); 
		drawLine(R6,Y6);
		System.out.println(Point2D.distance(B6, I1)/Point2D.distance(B6, Y6)); 
		System.out.println(Point2D.distance(G0, inter)/Point2D.distance(G0, R0)); 
		System.out.println(Point2D.distance(G6, I2)/Point2D.distance(G6, R6)); 
		System.out.println(Point2D.distance(I2, inter)/Point2D.distance(I2, I1)); 
	
		
		
		Point2D inter2=Droite.intersection(new Droite(R0,Y0),new Droite(I1,I2)); 
		drawPoint(inter2); 
		System.out.println(Point2D.distance(R0,inter2)/Point2D.distance(R0,Y0));
		System.out.println(Point2D.distance(inter,I1)/Point2D.distance(inter,inter2));
		
		primeIP.setColor(Color.RED); 
		
		Pos3D BT19=new Pos3D ( 0.313489, 1.098830, 0.375803) ;
		 
		Pos3D YT19=new Pos3D( -0.744356, 0.944492, -0.028258); 
	
		Pos3D RT19=new Pos3D( -0.919162, 0.486844, 0.604197); 
		
		Pos3D GT19=new Pos3D( 0.138682, 0.641181, 1.008258) ; 
		
		
		double prop3=(0.98-YT19.getY())/(BT19.getY()-YT19.getY()); 
		System.out.println("---> "+prop3);
		//prop=1-prop; 
		Point2D I3=new Point2D(prop3*BT19.getX()+(1-prop3)*YT19.getX(),prop3*BT19.getZ()+(1-prop3)*YT19.getZ());
		drawPoint(I3);
		
		double prop4=(0.98-BT19.getY())/(GT19.getY()-BT19.getY()); 
		System.out.println("---> "+prop4);
		//prop4=1-prop4; 
		Point2D I4=new Point2D(prop4*GT19.getX()+(1-prop4)*BT19.getX(),prop4*GT19.getZ()+(1-prop4)*BT19.getZ());
		drawPoint(I4);
		drawLine(I3,I4); 
		
		Point2D inter3=Droite.intersection(new Droite(G0,R0),new Droite(I3,I4));
		drawPoint(inter3); 
		
		Point2D inter4=Droite.intersection(new Droite(B0,Y0),new Droite(I3,I4));
		drawPoint(inter4); 
		
		Point2D B19=new Point2D( 0.313489,  0.375803); 
		Point2D Y19=new Point2D( -0.744356,  -0.028258) ;
		Point2D R19=new Point2D( -0.919162, 0.604197); 
		Point2D G19=new Point2D ( 0.138682,1.008258);  
		Droite B19Y19=new Droite(B19,Y19); 
		Droite B19G19=new Droite(B19,G19);
		Droite R19G19=new Droite(R19,G19); 
		Droite R19Y19=new Droite(R19,Y19);
		drawLine(B19,Y19); 
		drawLine(B19,G19);
		drawLine(R19,G19); 
		drawLine(R19,Y19);
		
	
		 show();

	}	
}
	